<!doctype html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>文字录入</title>
  <style>
    canvas {
      display: block;
      margin: 0 auto;
    }
    #controller {
      padding: 20px;
      text-align: center;
    }
  </style>
</head>
<body>
<canvas id="canvas"></canvas>
<div id="controller">
  <button type="button" id="clear">清除</button>
</div>
<script>
  var WIDTH = Math.min(800, document.body.clientWidth)
  var HEIGHT = WIDTH

  var canvas = document.getElementById('canvas')
  var context = canvas.getContext('2d')

  canvas.width = WIDTH
  canvas.height = HEIGHT

  backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || 1
  ratio = (window.devicePixelRatio || 1) / backingStore;

  if (ratio > 1) {
    canvas.style.width = WIDTH + 'px'
    canvas.style.height = HEIGHT + 'px'
    canvas.width *= ratio
    canvas.height *= ratio
    context.scale(ratio, ratio)
  }

  drawGrid()

  function drawGrid() {
    context.save()

    context.strokeStyle = 'rgb(230,11,9)'

    context.beginPath()
    context.moveTo(3, 3)
    context.lineTo(WIDTH - 3, 3)
    context.lineTo(WIDTH - 3, WIDTH - 3)
    context.lineTo(3, WIDTH - 3)
    context.closePath()
    context.lineWidth = 6
    context.stroke()

    context.beginPath()
    context.moveTo(0, 0)
    context.lineTo(WIDTH, HEIGHT)

    context.moveTo(WIDTH, 0)
    context.lineTo(0, HEIGHT)

    context.moveTo(WIDTH/2, 0)
    context.lineTo(WIDTH/2, HEIGHT)

    context.moveTo(0, HEIGHT/2)
    context.lineTo(WIDTH, HEIGHT/2)

    context.lineWidth = 1
    context.stroke()

    context.restore()
  }

  var btn = document.getElementById('clear')
  btn.onclick = function () {
    context.clearRect(0, 0, WIDTH, HEIGHT)
    drawGrid()
  }


  var isMouseDown = false
  var lastLoc = {x:0, y:0}
  var lastTimestamp = 0
  var lastLineWidth = -1

  function beginStroke(point) {
    isMouseDown = true
    lastLoc = windowToCanvas(point.x, point.y)
    lastTimestamp = Date.now()
  }
  function endStroke() {
    isMouseDown = false
  }
  function moveStroke(point) {
    var curLoc = windowToCanvas(point.x, point.y)
    var curTimestamp = Date.now()

    var s = calcDistance(curLoc, lastLoc)
    var t = curTimestamp - lastTimestamp
    var lineWidth = calcLineWidth(t, s)

    // draw
    context.beginPath()
    context.moveTo(lastLoc.x, lastLoc.y)
    context.lineTo(curLoc.x, curLoc.y)

    context.strokeStyle = 'black'
    context.lineWidth = lineWidth
    context.lineCap = 'round'
    context.lineJoin = 'round'
    context.stroke()

    lastLoc = curLoc
    lastTimestamp = curTimestamp
    lastLineWidth = lineWidth
  }

  canvas.onmousedown = function (e) {
    e.preventDefault()
    beginStroke({x:e.clientX, y:e.clientY})
  }
  canvas.onmouseup = function (e) {
    e.preventDefault()
    endStroke()
  }
  canvas.onmouseout = function (e) {
    e.preventDefault()
    endStroke()
  }
  canvas.onmousemove = function (e) {
    e.preventDefault()
    if (isMouseDown) {
      moveStroke({x:e.clientX, y:e.clientY})
    }
  }

  // mobile
  canvas.addEventListener('touchstart', function (e) {
    e.preventDefault()
    var touch = e.touches[0]
    beginStroke({x:touch.pageX, y:touch.pageY})
  })
  canvas.addEventListener('touchmove', function (e) {
    e.preventDefault()
    if (isMouseDown) {
      var touch = e.touches[0]
      moveStroke({x:touch.pageX, y:touch.pageY})
    }
  })
  canvas.addEventListener('touchend', function (e) {
    e.preventDefault()
    endStroke()
  })


  function windowToCanvas(x, y) {
    var box = canvas.getBoundingClientRect()
    return {
      x: Math.round(x - box.left),
      y: Math.round(y - box.top)
    }
  }

  function calcDistance(loc1, loc2) {
    return Math.sqrt( Math.pow((loc1.x - loc2.x), 2) + Math.pow((loc1.y - loc2.y), 2) )
  }

  var maxLW = 10
  var minLW = 1
  var maxV = 3
  var minV = 0.1

  function calcLineWidth(t, s) {
    var v = s/t
    var resultLineWidth

    if (v <= minV)
      resultLineWidth = maxLW
    else if (v >= maxV)
      resultLineWidth = minLW
    else
      resultLineWidth = maxLW - (v - minV)/(maxV-minV)*(maxLW-minLW)

    if (lastLineWidth == -1)
      return resultLineWidth

    return lastLineWidth*.65 + resultLineWidth*.35
  }
</script>
</body>
</html>